export default class draw {
  // 记录鼠标是否按下
  private mouseDown: boolean = false
  // 画板的dom对象
  private canvas: HTMLCanvasElement
  // 绘制对象
  private ctx: CanvasRenderingContext2D
  // 绘制记录
  private history: string[] = []
  // 当前撤回了几步
  private recallStep: number = 0
  // 绘画配置对象
  private config = {
    lineWidth: 2, // 线宽
    strokeStyle: 'red', // 线条颜色
    lineCap: 'round', // 设置线条两端圆角
    lineJoin: 'round', // 线条交汇处圆角
  }

  private fileName: string

  constructor(name: string, fileName: string = '签名') {
    this.fileName = fileName

    this.canvas = document.querySelector(name) as HTMLCanvasElement

    // 规定 canvas 的宽高
    const { clientHeight, clientWidth } = this.canvas
    this.canvas.height = clientHeight
    this.canvas.width = clientWidth

    this.ctx = this.canvas.getContext('2d') as CanvasRenderingContext2D

    // 把空白图保存进步骤
    this.history.push(this.preservation())
  }

  // 获取画布中的内容
  preservation() {
    return this.canvas.toDataURL('image/png', {
      width: this.canvas.width,
      height: this.canvas.height,
      quality: 1,
    })
  }

  // 清空画布
  canvasEmptying() {
    this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
    this.history.push(this.preservation())
  }

  // 鼠标按下事件 / 开始绘制
  startDrawing(event: MouseEvent) {
    const { offsetX, offsetY } = event
    this.ctx.beginPath()

    // 根据配置文件设置相应配置
    this.ctx.lineWidth = this.config.lineWidth
    this.ctx.strokeStyle = this.config.strokeStyle
    this.ctx.lineCap = this.config.lineCap as CanvasLineCap
    this.ctx.lineJoin = this.config.lineJoin as CanvasLineJoin

    // 创建绘制开始
    this.ctx.moveTo(offsetX, offsetY)

    // 标记为鼠标按下
    this.mouseDown = true

    // 当从新开始绘制时,初始化撤回信息
    if (this.recallStep) {
      // 把被撤销的步骤全部清空掉
      this.history.splice(0 - this.recallStep)
      this.recallStep = 0
    }
  }

  // 鼠标移动过程 / 绘制
  Drawing(event: MouseEvent) {
    // 只有在鼠标按下时才触发
    if (!this.mouseDown) return
    // 获取当前坐标点位
    const { offsetX, offsetY } = event
    // 绘制一段路线
    this.ctx.lineTo(offsetX, offsetY)

    // 绘制
    this.ctx.stroke()
  }

  // 鼠标抬起 / 结束绘制
  endDrawing() {
    // 只有在鼠标按下时才触发
    if (!this.mouseDown) return
    // 结束绘制
    this.ctx.closePath()
    // 移除鼠标移动或手势移动监听器
    // 标记为鼠标抬起
    this.mouseDown = false
    // 保存当前绘制
    this.history.push(this.preservation())
  }

  // 下载图片
  downLoad() {
    const a = document.createElement('a')
    // 设置 a 标签的下载文件名
    a.download = `${this.fileName}.png`
    // 设置 a 标签的跳转路径为 文件流地址
    a.href = this.preservation()
    // 手动触发 a 标签的点击事件
    a.click()
    // 移除 a 标签
    a.remove()
  }

  // 撤销or取消撤销 / 上一步or下一步
  private step(sign: boolean = true) {
    // 获取步骤表
    const url = this.history[this.history.length - this.recallStep - (sign ? 2 : 0)]

    if (!url) {
      console.log(sign ? '没有上一步了' : '没有下一步了')
      return
    }

    // 创建一个img标签
    const img = document.createElement('img')
    // 从历史记录中取出上一步的图片信息
    img.src = url
    // 图片标签加载完成后绘制到画布中
    img.addEventListener('load', () => {
      this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height)
      this.ctx.drawImage(img, 0, 0, this.canvas.width, this.canvas.height)
      // 绘制完成后释放标签
      img.remove()
      // 撤回步骤+1或者-1
      sign ? this.recallStep++ : this.recallStep--
    })
  }

  previousStep() {
    this.step(true)
  }
  nextStep() {
    this.step(false)
  }
}
